#ifndef __CONTROL2DBASE__
#define __CONTROL2DBASE__

#include "ControlBase.h"
#include "..\Math\MathHelper.h"

#include <stack>

#include <wx\string.h>
#include <wx\thread.h>
#include <wx\utils.h>
#include <wx\timer.h>

class ControlTimer : public wxTimer
{
public:
	class Control2DBase *Control;
	wxStopWatch watch;

	ControlTimer()
	{
		watch.Start();
	}

	void Notify();
};

/// <summary>
/// The base class for 2D-based schematic rendering controls.
/// </summary>
class Control2DBase : public ControlBase
{
	friend class ControlTimer;

protected:
	Point2f _offset, _delta;
	Point2i _pos;
    bool _moving;
	bool rMoving; 
	float _scale;
	bool _multiLayer;
	RendererBase *_drawingRenderer;
	ControlTimer _timer;
	float camera_x;
	float camera_y;
	float camera_z;

	Point3f GetOGLPos(const float &x, const float &y, const float &z);

public:
	~Control2DBase();

	/// <summary>
	/// Constructor.
	/// </summary>
	/// <param name="viewport">The viewport this control renders.</param>
	Control2DBase(const Viewport &viewport, RendererBase *renderer);

	static wxMutex *GetSchematicMutex();
	static wxCondition *GetSchematicCondition();

	/// <summary>
	/// Render all lower layers.
	/// </summary>
	const bool &GetMultiLayer() const;
	void SetMultiLayer(const bool &value);

	/// <summary>
	/// The size of a chunk in pixels.
	/// </summary>
	int GetChunkSizeInPixels() const { return 16 * 16; }

	/// <summary>
	/// The offset of the camera.
	/// </summary>
	const Point2f &GetOffset() const;
	void SetOffset(const Point2f &value);

	/// <summary>
	/// The scale of the camera.
	/// </summary>
	const float &GetScale() const;
	void SetScale(const float &value);

	/// <summary>
	/// Resets all values to default.
	/// </summary>
	void ResetValues();

	/// <summary>
	/// Handle the mousedown event.
	/// </summary>
	/// <param name="position">Position of the mouse</param>
	/// <param name="button">Button pressed</param>
	void MouseDown(const Point2i &position, const MouseButton &button);

	/// <summary>
	/// Handle the mousemove event.
	/// </summary>
	/// <param name="position">Position of the mouse</param>
	/// <param name="button">Button pressed</param>
	void MouseMove(const Point2i &position, const MouseButton &button);

	/// <summary>
	/// Handle the mouseup event.
	/// </summary>
	/// <param name="position">Position of the mouse</param>
	/// <param name="button">Button pressed</param>
	void MouseUp(const Point2i &position, const MouseButton &button);

	/// <summary>
	/// Handle the mousewheel event.
	/// </summary>
	/// <param name="detents">Detents moved.</param>
	void MouseWheel(const int &detents);
	virtual void DrawChunk3D(const int &x, const int &y, const int &z, const int &px, const int &py, const int &pz);

	/// <summary>
	/// Handle the draw event.
	/// </summary>
	void Draw();
	Point2i PointToScreen(const Point2i &p) const;
	bool ChunkVisible(const int &x, const int &y) const;
	void CreateThread();
};

#endif